// CHAPTER 2 OF OBJECT ORIENTED JAVASCRIPT
// PRIMITIVE DATA TYPES, Arrays, Loops, and conditions
mainchapter("2 PRIMITIVE DATA TYPES, Arrays, Loops, and conditions");

(function(){
	try{
		// 2.1 VARIABLES
		chapter("2.1 VARIABLES");
		var a;
		var thisIsAVariable;
		var _and_this_too;
		var mix12three;
		assertEquals(a,undefined); // scope issue..
		success("2.1.1a DECLARE VALID VARIABLES");
	}catch(e){
		$ERROR("2.1.1a DECLARE VARIABLE FAILED: "+e.message);
	}
	try{
		eval("var 2trhee4five"); // var can't start with a number
		$ERROR("2.1.1b variable name can't start with a number");
	}catch(e){
		success("2.1.1b DENY DECLARE INVALID VARIABLES: "+e.message);
	}
	try{
		// simple assigns
		var a = 1;
		var v1,v2,v3= 'hello', v4 = 4, v5;
		assertEquals(a,1);
		assertEquals(v1,undefined);
		assertEquals(v3,'hello');
		assertEquals(v4,4);
		// case sensitive
		var case_matters = 'lower';
		var CASE_MATTERS = 'upper';
		assertEquals(case_matters,'lower');
		assertEquals(CASE_MATTERS,'upper');
		success("2.1.2 ASSIGN VARIABLES");
	}catch(e){
		$ERROR("2.1.2 ASSIGN VARIABLES: "+e.message);
	}
	try{
		eval("onbekende_var;");
		$ERROR("2.1.3 ACCESS UNDEFINED VARIABLES > ERROR EXPECTED");
	}catch(e){
		success("2.1.3 ACCESS UNDEFINED VARIABLES / ERROR EXCPETED: "+e.message);
	}
})();

// execute thisone in the global scope, refreshing causes narcissus to cache this
try{
	var unique_var_name;
	assertEquals(unique_var_name,undefined); // scope issue..
	unique_var_name = 2;
	success("2.1.4 GLOBAL VARIABLES ARE NOT CACHED");
}catch(e){
	$ERROR("2.1.4 GLOBAL VARIABLE WAS CACHED : "+e.message);
}

(function(){
	// 2.2 OPERATORS
	chapter("2.2 OPERATORS");
	try{
		assertEquals(1+2,3);
		var a = 1;
		var b = 2;
		assertEquals(a+1,2);
		assertEquals(b+2,4);
		assertEquals(a+b,3);
		var c = a+b;
		assertEquals(c,3);
		success("2.2.1a OPERATORS +");
	}catch(e){
		$ERROR("2.2.1a OPERATORS +: "+e.message);
	}
	try{
		assertEquals(6%3,0);
		assertEquals(5%3,2);
		success("2.2.1b OPERATORS %");
	}catch(e){
		$ERROR("2.2.1b OPERATORS %: "+e.message);
	}
	try{
		var a = 123; var b= a++;
		assertEquals(b,123);
		assertEquals(a,124);
		var c = 123; var d= ++c;
		assertEquals(d,124);
		assertEquals(c,124);
		success("2.2.1c OPERATORS ++ prefix/suffix");
	}catch(e){
		$ERROR("2.2.1c OPERATORS ++: "+e.message);
	}
	try{
		var a = 123; var b= a--;
		assertEquals(b,123);
		assertEquals(a,122);
		var c = 123; var d= --c;
		assertEquals(d,122);
		assertEquals(c,122);
		success("2.2.1d OPERATORS -- prefix/suffix");
	}catch(e){
		$ERROR("2.2.1d OPERATORS -- : "+e.message);
	}
	try{
		var a=5;
		a += 3;
		assertEquals(a,8);
		a -= 3;
		assertEquals(a,5);
		a*=2;
		assertEquals(a,10);
		a /= 5;
		assertEquals(a,2);
		a %= 2;
		assertEquals(a,0);
		success("2.2.1e OPERATORS +=, -=, *=, /=, %=");
	}catch(e){
		$ERROR("2.2.1e OPERATORS +=, -=, *=, /=, %=: "+e.message);
	}
	try{
		assertEquals(1 + 2 * 3 , 7);
		assertEquals(1 + (2 * 3) , 7);
		assertEquals((1 + 2) * 3 , 9);
		success("2.2.2 OPERATOR PRECEDENCE");
	}catch(e){
		$ERROR("2.2.2 OPERATOR PRECEDENCE: "+e.message);
	}
	try{
		var b = 5;
		assertEquals(true || (b=6),true);
		assertEquals(b,5);
		assertEquals(true && (b=6),6);
		assertEquals(b,6);
		assertEquals(true || "something",true);
		assertEquals(true && "something","something");
		success("2.2.3 LAZY EVALUATION");
	}catch(e){
		$ERROR("2.2.3 LAZY EVALUATION: "+e.message);
	}
	
})();

(function(){
	// 2.3 NUMBERS
	chapter("2.3 STRINGS");
	try{
		var n = 1;
		assertEquals(typeof n,"number");
		n = 1234;
		assertEquals(typeof n,"number");
		var n2 = 1.23;
		assertEquals(typeof n2,"number");
		assertEquals(typeof 123,"number");
		success("2.3.1 typeof, number (ints and floats)");
	}catch(e){
		$ERROR("2.3.1 typeof, number (ints and floats): "+e.message);
	}
	try{
		var n3 = 0377;
		assertEquals(typeof n3,"number");
		assertEquals(n3,255);
		success("2.3.2 octal numbers");
	}catch(e){
		$ERROR("2.3.2 octal numbers: "+e.message);
	}
	try{
		var n4 = 0x00;
		assertEquals(typeof n4,"number");
		assertEquals(n4,0);
		var n5 = 0xff;
		assertEquals(typeof n5,"number");
		assertEquals(n5,255);
		success("2.3.3 hexadecimal numbers");
	}catch(e){
		$ERROR("2.3.3 hexadecimal numbers: "+e.message);
	}
	try{
		assertEquals(1e1,10);
		assertEquals(1e+1,10);
		assertEquals(2e+3,2000);
		assertEquals(typeof 2e+3,"number");	
		success("2.3.4a exponent literals positive (e.g. 2e+3)");
		assertEquals(typeof 2e-3,"number");	
		assertEquals(2e-3,(0.002));
		assertEquals(123.456E-3,0.123456);
		success("2.3.4b exponent literals negative (e.g. 2e-3)");
	}catch(e){
		$ERROR("2.3.4 exponent literals: "+e.message);
	}
	try{
		assertEquals(1e309,Infinity);
		assertEquals(1e308,1e+308);
		var a = 6/0;
		assertEquals(a,Infinity);
		var i = -Infinity;
		assertEquals(i,-Infinity);
		assertEquals(typeof i,"number");
		assertEquals(Infinity-Infinity,NaN);
		assertEquals(Infinity-20,Infinity);
		assertEquals(Infinity*3,Infinity);
		assertEquals(Infinity/2,Infinity);
		success("2.3.5 Infinity");
	}catch(e){
		$ERROR("2.3.5 Infinity: "+e.message);
	}
	try{
		assertEquals(typeof NaN,"number");
		var a = NaN;
		assertEquals(a,NaN);
		var b = 10 * "f";
		assertEquals(b,NaN);
		assertEquals(1+2+NaN,NaN);
		var i = 1 + undefined;
		assertEquals(i,NaN);
		assertEquals(1*undefined,NaN);
		success("2.3.6 NaN");
	}catch(e){
		$ERROR("2.3.6 NaN: "+e.message);
	}
})();

(function(){
	// 2.4 Strings
	chapter("2.4 STRINGS");
	try{
		var s = "some characters";
		assertEquals(typeof s,"string");
		var s = 'some characters and numbers 123 5.87';
		assertEquals(typeof s,"string");
		var s = '1';
		assertEquals(typeof s,"string");
		var s = "";
		assertEquals(typeof s,"string");
		success("2.4.1 typeof string");
	}catch(e){
		$ERROR("2.4.1 typeof string : "+e.message);
	}
	try{
		var s1 = "one"; var s2 = "two"; var s = s1+s2;
		assertEquals(typeof s,"string");
		assertEquals(s,"onetwo");
		success("2.4.2 concat string");
	}catch(e){
		$ERROR("2.4.2 concat string : "+e.message);
	}
	try{
		var s = '1'; s = 3*s;
		assertEquals(typeof s,"number");
		assertEquals(s,3);
		var s = "100";
		assertEquals(typeof s,"string");
		s = s*1;
		assertEquals(typeof s,"number");
		var d = '101 dalmatians';
		assertEquals(d*1,NaN);
		var n = 1;
		assertEquals(typeof n,"number");
		n = "" + n;
		assertEquals(typeof n,"string");
		assertEquals(n,"1");
		success("2.4.3 string conversions");
	}catch(e){
		$ERROR("2.4.3 string conversions: "+e.message);
	}
})();

(function(){
	// 2.5 Booleans
	chapter("2.5 BOOLEANS AND LOGICAL OPERATORS");
	try{
		var b = true;
		assertEquals(typeof b,"boolean");
		var b = false;
		assertEquals(typeof b,"boolean");
		var b = "true";
		assertEquals(typeof b,"string");
		success("2.5.1 typeof boolean");
	}catch(e){
		$ERROR("2.5.1 typeof boolean : "+e.message);
	}
	try{
		var b = !true;
		assertEquals(b,false);
		var b = !!true;
		assertEquals(b,true);
		success("2.5.2a LOGICAL OPERATORS: !not");
	}catch(e){
		$ERROR("2.5.2 LOGICAL OPERATORS : "+e.message);
	}
	try{
		assertEquals(true && true,true);
		assertEquals(true && false,false);
		assertEquals(false && true,false);
		assertEquals(false && false,false);
		assertEquals(true || true,true);
		assertEquals(true || false,true);
		assertEquals(false || true,true);
		assertEquals(false || false,false);
		success("2.5.2b LOGICAL OPERATORS: && ||");
	}catch(e){
		$ERROR("2.5.2 LOGICAL OPERATORS : "+e.message);
	}
	try{
		assertEquals(!!undefined,false);
		assertEquals(!!null,false);
		success("2.5.3 BOOLEAN CONVERSION");
	}catch(e){
		$ERROR("2.5.3 BOOLEAN CONVERSION : "+e.message);
	}
})();

(function(){
	// 2.6 COMPARISON
	chapter("2.6 COMPARISON");
	try{
		assertEquals(1 == 1,true);
		assertEquals(1 == 2,false);
		assertEquals(1 == '1',true);
		assertEquals(1 === '1',false);
		assertEquals(1 === 1,true);
		success("2.6a COMPARISON OPERATORS ==");
	}catch(e){
		$ERROR("2.6a COMPARISON OPERATORS == : "+e.message);
	}
	try{
		assertEquals(1 != 1,false);
		assertEquals(1 != '1',false);
		assertEquals(1 != 2,true);
		assertEquals(1 !== 1,false);
		assertEquals(1 !== '1',true);
		success("2.6b COMPARISON OPERATORS !=");
	}catch(e){
		$ERROR("2.6b COMPARISON OPERATORS != : "+e.message);
	}
	try{
		assertEquals(1 > 1,false);
		assertEquals(33 > 22,true);
		assertEquals(1 >= 1,true);
		assertEquals(1 < 1,false);
		assertEquals(1 < 2,true);
		assertEquals(1 <= 1,true);
		assertEquals(1 <= 2,true);
		success("2.6c COMPARISON OPERATORS > <");
	}catch(e){
		$ERROR("2.6c COMPARISON OPERATORS > < : "+e.message);
	}
})();

(function(){
	// 2.7 ARRAYS
	chapter("2.7 ARRAYS");
	try{
		var a = [];
		assertEquals(typeof a, "object");
		var a = [1,2,3];
		assertEquals(a[0],1);
		assertEquals(a[1],2);
		success("2.7.1 Init Arrays ");
	}catch(e){
		$ERROR("2.7.1 Init Arrays : "+e.message);
	}
	try{
		var a = [1,2,3];
		a[2] = "three";
		assertEquals(a[0],1);
		assertEquals(a[2],"three");
		a[3] = "four";
		assertEquals(a[1],2);
		assertEquals(a[3],"four");
		var a = [1,2,3];
		a[6] = 'new';
		assertEquals(a[1],2);
		assertEquals(a[4],undefined);
		assertEquals(a[5],undefined);
		assertEquals(a[6],'new');
		success("2.7.2 Adding/Updating Arrays ");
	}catch(e){
		$ERROR("2.7.2  Adding/Updating Arrays : "+e.message);
	}
	try{
		var a = [1,2,3];
		assertEquals(delete a[1],true);
		assertEquals(a[1],undefined);
		assertEquals(a[2],3);
		success("2.7.3 Deleting elements from Arrays ");
	}catch(e){
		$ERROR("2.7.3 Deleting elements from Arrays : "+e.message);
	}	
	try{
		var a = [1,"two",false,null,undefined];
		assertEquals(a[0],1);
		assertEquals(a[1],"two");
		assertEquals(a[2],false);
		assertEquals(a[3],null);
		assertEquals(a[4],undefined);
		a[5] = [1,2,3];
		assertEquals(a[5][0],1);
		assertEquals(a[5][2],3);
		var a = [[1,2,3],[4,5,6]];
		assertEquals(a[0][1],2);
		assertEquals(a[1][1],5);
		success("2.7.4 Arrays of Arrays ");
	}catch(e){
		$ERROR("2.7.4 Arrays of Arrays : "+e.message);
	}
	try{
		var s = 'one';
		assertEquals(s[0],'o');
		assertEquals(s[1],'n');
		success("2.7.5 String Arrays ");
	}catch(e){
		$ERROR("2.7.5 String Arrays : "+e.message);
	}
})();

(function(){
	// 2.8 CONDITIONS AND LOOPS
	chapter("2.8 CONDITIONS AND LOOPS");
	try{
		if(false)
		{
			$ERROR("2.8.1 IF-STATEMENT");
		}
		var result="", somevar = undefined;
		if(typeof somevar !== "undefined"){result = "yes";}
		assertEquals(result,"");
		somevar = 123;
		if(typeof somevar !== "undefined"){result = "yes";}
		assertEquals(result,"yes");
		result = (somevar === 123 ? "equal" : "notequal");
		assertEquals(result,"equal");
		result = (somevar === 122 ? "equal" : "notequal");
		assertEquals(result,"notequal");
		success("2.8.1 IF-STATEMENT");
	}catch(e){
		$ERROR("2.8.1 IF-STATEMENT : "+e.message);
	}
	try{
		var a = '1';result = "";
		switch(a)
		{
			case 1:
				$ERROR("2.8.2 SWITCH ('1' === 1) ");break;
			case '1':
				result = "ok";
				break;
			default:
				$ERROR("2.8.2 SWITCH default ");break;
		}
		switch(a)
		{
			case 2:
				$ERROR("2.8.2 SWITCH ('1' === 2) ");break;
			case '2':
				$ERROR("2.8.2 SWITCH ('1' === '2' ");break;
			default:
				result = "ok2";
				break;
		}
		assertEquals(result,"ok2");
		success("2.8.2 SWITCH");
	}catch(e){
		$ERROR("2.8.2 SWITCH : "+e.message);
	}
	try{
		var i = 0;
		while(i < 10)
		{
			i++;
		}
		assertEquals(i,10);
		var i = 0;
		do
		{
			i++;
		}while(i < 5)
		assertEquals(i,5);
		success("2.8.3 WHILE / DO WHILE");
	}catch(e){
		$ERROR("2.8.3 WHILE / DO WHILE : "+e.message);
	}
	try{
		var result = 0;
		for(var i = 0; i<10;i++){
			result += 10;
		}
		assertEquals(result,100);
		for(var i = 0,result=0;i<10;i++,result+=5){
			// nothing here
		}
		assertEquals(result,50);
		var i = 0,result = 1000;
		for(;;){
			result+=10;
			if(++i == 5){
				break;
			}
		}
		assertEquals(result,1050);
		success("2.8.4a FOR-LOOP");
		var a = ["a","b","c","d","e"],result = "";
		for(var i in a)
		{
			result +=a [i];
		}
		assertEquals(result,"abcde");
		success("2.8.4b FOR IN LOOP");
	}catch(e){
		$ERROR("2.8.4 FOR-LOOP : "+e.message);
	}
})();



